/*
 * Created on Feb 15, 2005
 * Created by dfhuynh
 */
package edu.mit.simile.longwell.ui.command;

import java.util.Comparator;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.servlet.ServletException;

import org.apache.log4j.Logger;
import org.apache.velocity.VelocityContext;

import edu.mit.simile.longwell.Profile;
import edu.mit.simile.longwell.query.IAnswer;
import edu.mit.simile.longwell.query.IQueryModel;
import edu.mit.simile.longwell.query.Query;
import edu.mit.simile.longwell.query.QueryException;
import edu.mit.simile.longwell.schema.IStructuredProperty;
import edu.mit.simile.longwell.tag.ITagModel;
import edu.mit.simile.longwell.ui.FlairMessage;
import edu.mit.simile.longwell.ui.FlairURL;
import edu.mit.simile.longwell.ui.InjectionManager;

/**
 * @author dfhuynh
 */
public class BrowseCommand extends CommandBase {
	final static private Logger s_logger = Logger.getLogger(BrowseCommand.class);

	/**
	 * @param injectionManager
	 */
	public BrowseCommand(InjectionManager injectionManager) {
		super(injectionManager);
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.flair.IFlairCommand#execute(edu.mit.simile.flair.FlairMessage)
	 */
	public void execute(FlairMessage msg) throws ServletException {
		try {
			VelocityContext vcContext = createContext(msg);

			if (msg.m_query.getRestrictions().size() > 0) {
				IAnswer answer = performQuery(msg, vcContext);

				fillContextWithAnswer(msg, vcContext, answer);

				msg.m_ve.mergeTemplate(
					"templates/commands/browse.vt",
					vcContext,
					msg.m_response.getWriter());
			} else {
				msg.m_response.sendRedirect(
					new FlairURL(msg).changeCommandQuery("start", "").toURLString());
			}
		} catch (Throwable e) {
			s_logger.error(e);
			e.printStackTrace();
		}

	}

	protected IAnswer performQuery(FlairMessage msg, VelocityContext vcContext) throws QueryException {
		Query query = msg.m_query;
		IQueryModel queryModel = (IQueryModel)
			msg.getProfile().getStructuredModel(IQueryModel.class);

		IAnswer answer = queryModel.query(query, false);

		return answer;
	}

	protected void fillContextWithAnswer(FlairMessage msg, VelocityContext vcContext, IAnswer answer) throws QueryException {
		vcContext.put("answer", answer);

		int pageIndex = 0;
		String page = msg.m_query.getFirstParamValue("page");
		if (page != null) {
			try {
				pageIndex = Integer.parseInt(page);
				pageIndex = Math.max(0, Math.min(pageIndex, answer.getPages().size() - 1));
			} catch (NumberFormatException e) {
				s_logger.warn("Bad page number " + page, e);
			}
		}
		vcContext.put("pageIndex", new Integer(pageIndex));

		vcContext.put("commonProperties", getCommonProperties(answer.getObjects(), msg));
	}

	protected SortedSet getCommonProperties(Set objects, FlairMessage msg) {
		Profile profile = msg.getProfile();

		SortedSet properties = new TreeSet(new Comparator() {
			String m_locale;

			public boolean equals(Object obj) {
				return false;
			}

			public int compare(Object o1, Object o2) {
				IStructuredProperty p1 = (IStructuredProperty) o1;
				IStructuredProperty p2 = (IStructuredProperty) o2;

				int i = p1.getLabel(m_locale).compareToIgnoreCase(p2.getLabel(m_locale));
				if (i == 0) {
					i = p1.getURI().compareTo(p2.getURI());
				}
				return i;
			}

			public Comparator init(String locale) {
				m_locale = locale;
				return this;
			}
		}.init(msg.m_locale));

		properties.addAll(
			profile.getSchemaModel().getSortedStructuredProperties(objects));

		// Default generic properties
		{
			properties.add(
				profile.getSchemaModel().getStructuredProperty(
					profile.getModel().createProperty(ITagModel.s_simile_tag)));
		}

		return properties;
	}
}
